#ifndef BUFFER_MERGE_H
#define BUFFER_MERGE_H

#include <stdbool.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>

#include "cola.h"
#include "termino_merge.h"
#include "utilidades.h"

/** ***********									*********** **
 ** ***********	DEFINICION DEL TIPO DE DATOS	*********** **
 ** ***********									*********** **/

typedef struct buffer buffer_t;

/*
 * Crea el buffer a partir del tamanio maximo recibido y el archivo
 * destino recibido. Lo devuelve luego de crearlo.
 */
buffer_t* buffer_crear(FILE* destino,unsigned long tamanio_maximo);

/*
 * Aumenta la cantidad total de terminos procesados. Se le suma
 * la cantidad recibida a la cantidad actual. Devuelve la nueva
 * cantidad o cero si no recibio buffer.
 */
unsigned long buffer_aumentar_procesados(buffer_t* buffer,unsigned long cantidad_procesados);

/*
 * Aumenta la cantidad de los valores distintos de cero en el merge.
 * Le suma la cantidad recibida al valor actual. Devuelve la nueva
 * cantidad o cero si no recibio buffer.
 */
unsigned long buffer_aumentar_distintos_de_cero(buffer_t* buffer,unsigned long cantidad);

/*
 * Devuelve la cantidad de terminos procesados por el buffer.
 * Si no recibe buffer, devuelve cero.
 */
unsigned long buffer_obtener_procesados(buffer_t* buffer);

/*
 * Devuelve la cantidad de valores distintos de cero procesados
 * por el buffer o cero si no recibe buffer.
 */
unsigned long buffer_obtener_distintos_de_cero(buffer_t* buffer);

/*
 * Devuelve el tamanio actual del buffer o cero si no recibe buffer.
 */
unsigned long buffer_ver_tamanio(buffer_t* buffer);

/*
 * Devuelve el tamanio maximo del buffer o cero si no recibe buffer.
 */
unsigned long buffer_ver_tamanio_maximo(buffer_t* buffer);

/*
 * Devuelve el puntero al archivo destino del buffer o NULL si no
 * recibe buffer.
 */
FILE* buffer_obtener_destino(buffer_t* buffer);

FILE* buffer_obtener_terminos_indice(buffer_t* buffer);

FILE* buffer_obtener_terminos_string(buffer_t* buffer);

/*
 * Devuelve true si la cola del buffer esta vacia o false en caso contrario.
 * Devuelve true si no recibe buffer.
 */
bool buffer_esta_vacio(buffer_t* buffer);

/*
 * Devuelve el siguiente termino en la cola del buffer recibido.
 * Devuelve NULL si no recibe buffer.
 */
termino_merge_t* buffer_obtener_siguiente(buffer_t* buffer);

/*
 * Limpia el buffer recibido en su respectivo archivo destino. Si no
 * recibe buffer, o el buffer no tiene archivo destino especificado
 * o la cola del mismo esta vacia, no hace nada. Actualiza la cantidad
 * de terminos procesados y valores distintos de cero.
 */
void buffer_limpiar(buffer_t* buffer);
/*
 * Encola el termino recibido en el buffer recibido. Si no recibe buffer
 * o termino no realiza ninguna accion.
 */
void buffer_encolar(buffer_t* buffer,termino_merge_t* termino);

/*
 * Agrega el termino recibido al buffer recibido. Se fija si el termino
 * entra en el buffer, si no entra, limpia el buffer y lo agrega. Si entra,
 * simplemente lo agrega.
 */
void buffer_agregar_termino(buffer_t* buffer,termino_merge_t* termino);

/*
 * Destruye el buffer recibido por parametro. Si no recibe buffer,
 * no realiza ninguna accion.
 */
void buffer_destruir(buffer_t* buffer);

#endif // BUFFER_MERGE_H

